/**
 * @file encode.h
 * @brief Кодирование между различными кодовыми страницами и Юникодом
 * @version 1.0
 * @date 12 августа 2011
 * @author Владимир Керимов
 */

#pragma once

/// @namespace qua
/// @brief Пространство имён программного инструментария Qualab
namespace qua
{
    /// @class encode
    /// @brief Инструментарий для перекодирования символов из кодовых страниц в Unicode и наоборот
    class encode
    {
    public:
        /// @enum codepage
        /// @brief Варианты кодировки данных char* или std::string
        enum codepage
        {
            cpDEFAULT   = 0,        ///< берётся кодовая страница заданная по-умолчанию
            cp437       = 437,      ///< исходная кодовая страница IBM PC
            cp866       = 866,      ///< кириллица MS-DOS (консоль Windows)
            cp1250      = 1250,     ///< центрально-европейская латиница Windows
            cp1251      = 1251,     ///< российская кириллица Windows
            cp1252      = 1252,     ///< западно-европейская латиница Windows
            KOI8R       = 20866,    ///< российская кириллица KOI8-R
            UTF8        = 65001,    ///< строка в формате UTF-8
            cpNONE      = -1        ///< кодовая страница не задана
        };

        static const int UNICODE_VERSION        = 6; ///< версия Unicode реализованная в данной библиотеке
        static const int UNICODE_VERSION_MINOR  = 0; ///< младшее число версии Unicode реализованной в данной библиотеке

        /// Кодировка из Unicode в char
        static char to_char( int code, codepage cp = cpDEFAULT );

        /// Кодировка из char в Unicode
        static int to_unicode( char sign, codepage cp = cpDEFAULT );

        /// Задать кодовую страницу использующуюся по умолчанию
        static void set_default_codepage( codepage cp );

        /// Возвращает кодовую страницу использующуюся по умолчанию
        static codepage get_default_codepage();

        /// Возвращает кодовую страницу по заданному имени
        static codepage read_codepage( const char* name );

        /// Возвращает имя заданной кодовой страницы
        static const char* codepage_name( codepage cp );

        static const int MAX_ASCII   = 0x7F;     ///< максимальный код ASCII символа
        static const int MAX_UCS2    = 0xFFFF;   ///< максимальный код UCS-2 символа
        static const int MAX_UNICODE = 0x10FFFF; ///< максимальный код Unicode символа (текущей версии)

        /// Проверка: символ с указанным кодом входит в ASCII
        static bool is_ascii( int code ) { return (code & MAX_ASCII) == code; }

        /// Проверка: символ с указанным кодом входит в UCS-2
        static bool is_ucs2( int code ) { return (code & MAX_UCS2) == code; }

        /// Проверка: символ Unicode с указанным кодом существует
        static bool is_unicode( int code ) { return code >= 0 && code <= MAX_UNICODE; }

        /// Проверка: символ с указанным кодом не входит в ASCII
        static bool is_not_ascii( int code ) { return !is_ascii( code ); }

        /// Проверка: символ с указанным кодом не входит в UCS-2
        static bool is_not_ucs2( int code ) { return !is_ucs2( code ); }

        /// Проверка: символа Unicode с указанным кодом не существует
        static bool is_not_unicode( int code ) { return !is_unicode( code ); }

        /// Проверка: символ входит в ASCII
        static bool is_ascii( char sign ) { return (sign & 0x80) == 0; }

        /// Проверка: символ не входит в ASCII
        static bool is_not_ascii( char sign ) { return !is_ascii( sign ); }

        /// Считывает код символа UTF-8 и возвращает число прочитанных байт
        static int read_utf8( const char* seq, int& res );

        /// Записывает код символа UTF-8 и возвращает число записанных байт
        static int to_utf8( int code, char* res );
    };
}
